
#include "miniutil/multinetservice.h"

namespace miniutil { namespace frame {

	MultinetPeer::MultinetPeer(miniutil::multinet::SocketMulplexService* ps, miniutil::soaddr addr)
	{
		mconnsoc = NULL;
		mstatus = STUS_IDLE;
		mraddr = addr;
		mpss = ps;
        mconntype = TYPE_ACTIVE;
	}

	MultinetPeer::MultinetPeer(miniutil::multinet::SocketMulplexService* ps, miniutil::soaddr addr, SOCKET soc)
	{
		mconnsoc = soc;
		mstatus = STUS_CONNECTED;
		mraddr = addr;
		mpss = ps;
        mconntype = TYPE_PASSIVE;
	}

	int MultinetPeer::SendoutData(miniutil::data::shared_buffer sbuf)
	{
		miniutil::auto_lock lk(&mtx);
		mtosendmsg.push_back(sbuf);
		return 0;
	}

	//int MultinetPeer::RetrieveData(char* pbuf, int len)
	//{
	//	miniutil::auto_lock lk(&mtx);
	//	return mrecvbuf.read(pbuf, len);
	//}

	int MultinetPeer::working()
	{
		int ret;
		if(mstatus == STUS_IDLE)
		{
			mconnsoc = miniutil::socketcmn::try_connect((sockaddr_in*)mraddr.get_sockaddr());
			if(mconnsoc == INVALID_SOCKET)
			{
				mstatus = STUS_CONN_FAIL;
				std::cout<<"MultinetPeer Connect Fail..."<<std::endl;
				return -1;
			}
			mpss->add_tcp_socket(mconnsoc, miniutil::multinet::EVT_CONNECTED);
			mstatus = STUS_CONNECTING;
		}
		else if(mstatus == STUS_CONNECTING)
		{
			if( mpss->is_connected(mconnsoc))
			{
				mstatus = STUS_CONNECTED;
				mpss->add_tcp_socket(mconnsoc, miniutil::multinet::EVT_WRITE_READY|miniutil::multinet::EVT_READ_READY);
				//mltmstactive = miniutil::date::currentSec();
			}
			else if(mpss->is_exception(mconnsoc))
			{
				mstatus = STUS_CONN_FAIL;
				std::cout<<"MultinetPeer Connect Fail..."<<std::endl;
				return -1;
			}
		}
		else if(mstatus == STUS_CONNECTED)
		{
			miniutil::auto_lock lk(&mtx);
			while(mpss->is_writeable(mconnsoc) && mtosendmsg.size() > 0)
			{
				miniutil::data::shared_buffer btos = mtosendmsg.front();
				ret = mpss->send(mconnsoc, btos->data(), (int)btos->length());
				mtosendmsg.erase(mtosendmsg.begin());
				if(ret == -1)
				{
					mstatus = STUS_CONN_BROKE;
					break;
				}
			}
			while(mpss->is_readable(mconnsoc))
			{
				std::pair<char*, unsigned int> writepos;
				mrecvbuf.getwritepos(writepos);
				if(writepos.second <= 0)
					break;
				ret = mpss->recv(mconnsoc, writepos.first, writepos.second);
				if(ret < 0)
				{
					mstatus = STUS_CONN_BROKE;
					std::cout<<"[MultinetPeer] read fail"<<std::endl;
					break;
				}
				else if(ret == 0)
				{
					mstatus = STUS_CONN_BROKE;
					std::cout<<"[MultinetPeer] connection close"<<std::endl;
					break;
				}
				else
				{
					mrecvbuf.more_content(ret);
				}
			}
		}
		return 0;
	}
} }
